package com.catazy.album.presentation.screen.albumlist

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.widget.SearchView.OnQueryTextListener
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.ElevatedCard
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.res.stringResource
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.catazy.album.R
import com.catazy.album.domain.model.Album
import com.catazy.album.presentation.screen.albumlist.AlbumListViewModel.UiState
import com.catazy.album.presentation.screen.albumlist.AlbumListViewModel.UiState.Content
import com.catazy.album.presentation.screen.albumlist.AlbumListViewModel.UiState.Error
import com.catazy.album.presentation.screen.albumlist.AlbumListViewModel.UiState.Loading
import com.catazy.base.common.res.Dimen
import com.catazy.base.presentation.activity.BaseActivity
import com.catazy.base.presentation.activity.BaseActivity.Companion.mainActivity
import com.catazy.base.presentation.activity.BaseFragment
import com.catazy.base.presentation.compose.composable.DataNotFoundAnim
import com.catazy.base.presentation.compose.composable.PlaceholderImage
import com.catazy.base.presentation.compose.composable.ProgressIndicator
import com.catazy.base.presentation.ext.hideKeyboard
import com.catazy.base.presentation.ext.initSearchBehaviour
import com.catazy.base.presentation.ext.showKeyboard
import org.koin.androidx.navigation.koinNavGraphViewModel

/**
 * - 作者: Tao
 * - 日期: 2024/12/24
 * - 时间: 09:54
 * - 描述: 表示专辑列表的UI片段。
 * 该类继承自BaseFragment，用于显示专辑列表，并处理与专辑列表相关的UI逻辑。
 */
internal class AlbumListFragment : BaseFragment() {

    /**
     * 使用koin进行依赖注入获取AlbumListViewModel实例。
     * 该实例在导航图中共享，以确保数据在导航过程中的持久性。
     */
    private val model: AlbumListViewModel by koinNavGraphViewModel(R.id.albumNavGraph)

    /**
     * 创建视图。
     *
     * @param inflater 用于将XML视图信息解析为视图对象的工具。
     * @param container 父视图组，用于将新创建的视图添加到其中。
     * @param savedInstanceState 保存的片段状态，可以在片段重新创建时使用。
     * @return 返回创建的视图。
     */
    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {

        return ComposeView(requireContext()).apply {
            setContent {
                AlbumListScreen(model)
            }
        }
    }

    /**
     * 在视图创建后调用，
     * 初始化搜索文本输入框的行为。
     * 该方法设置搜索文本输入框的监听器，以处理搜索查询的提交和更改事件。
     *
     * @param view 创建的视图。
     * @param savedInstanceState 保存的片段状态。
     */
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // 首次获取默认专辑列表
        model.onEnter()

        mainActivity.searchTextInputEditText?.let { editText ->
            // 初始化搜索文本输入框的行为
            //  生命周期作用域：传入 viewLifecycleOwner.lifecycleScope，确保搜索行为与片段的生命周期相关联
            //  最小查询大小：传入 MINIMUM_PRODUCT_QUERY_SIZE，定义了搜索查询的最小长度
            //  查询提交延迟：传入 DELAY_BEFORE_SUBMITTING_QUERY，定义了在提交查询之前需要等待的时间
            //  查询监听器：传入一个 OnQueryTextListener 对象，该对象实现了两个方法：
            //      onQueryTextSubmit(query: String?)：当用户提交搜索查询时调用。该方法会隐藏键盘并调用 model.onEnter(query) 方法。
            //      onQueryTextChange(newText: String?)：当用户更改搜索查询时调用。
            //      如果新的查询文本为空或空白，该方法会隐藏键盘并调用 configureDefaultAppBar(mainActivity) 方法。
            editText.initSearchBehaviour(
                viewLifecycleOwner.lifecycleScope,
                MINIMUM_PRODUCT_QUERY_SIZE,
                DELAY_BEFORE_SUBMITTING_QUERY,
                object : OnQueryTextListener {
                    /**
                     * 当搜索查询提交时调用。
                     * 该方法隐藏键盘，重置应用栏，并使用新的搜索查询更新UI。
                     *
                     * @param query 提交的搜索查询。
                     * @return 返回true表示事件已处理。
                     */
                    override fun onQueryTextSubmit(query: String?): Boolean {
                        editText.hideKeyboard()
                        configureDefaultAppBar(mainActivity)
                        model.onEnter(query)
                        return true
                    }

                    /**
                     * 当搜索查询更改时调用。
                     * 如果查询为空或空白，该方法重置应用栏。
                     *
                     * @param newText 新的搜索查询文本。
                     * @return 返回true表示事件已处理。
                     */
                    override fun onQueryTextChange(newText: String?): Boolean {
                        if (newText.isNullOrBlank()) {
                            editText.hideKeyboard()
                            configureDefaultAppBar(mainActivity)
                        }
                        return true
                    }

                }
            ).also { editText.text?.clear() }

        }
    }

    companion object {
        /**
         * 最小产品查询大小，用于搜索。
         */
        const val MINIMUM_PRODUCT_QUERY_SIZE = 1

        /**
         * 在提交查询之前延迟的时间。
         */
        const val DELAY_BEFORE_SUBMITTING_QUERY = 500L

        /**
         * 配置应用栏的静态方法。
         * 该方法设置应用栏的属性，如高程、可见性和布局转换。
         *
         * @param baseActivity 基础活动，其应用栏需要配置。
         */
        fun configureAppBar(baseActivity: BaseActivity) {
            baseActivity.apply {
                appBarLayout?.apply {
                    // 移除应用栏下的阴影效果，实现扁平化的视觉风格
                    elevation = 0f
                    // 设置应用栏的可见性为true
                    isVisible = true
                    // 移除布局转换动画，以避免不必要的视觉干扰
                    layoutTransition = null
                }

                mainAppToolbar?.layoutTransition = null

            }
        }

        /**
         * 配置默认应用栏的静态方法。
         * 该方法重置搜索输入框和应用栏的属性，以显示默认状态。
         *
         * @param baseActivity 基础活动，其应用栏需要配置为默认状态。
         */
        private fun configureDefaultAppBar(baseActivity: BaseActivity) {
            baseActivity.apply {
                searchTextInputEditText?.hideKeyboard()
                searchLayout?.updateLayoutParams {
                    width = ViewGroup.LayoutParams.WRAP_CONTENT
                }
                searchTextInputLayout?.apply {
                    isVisible = false
                }
                mainAppToolbar?.apply {
                    // 在主线程上发布一个可运行任务以更新UI元素。
                    post {
                        // 设置了屏幕标题
                        setTitle(R.string.album)
                        // 移除了应用栏中的任何Logo（如果存在）
                        logo = null
                    }
                    // 清除任何现有的菜单项，确保在加载新菜单之前有一个干净的状态
                    menu?.clear()
                    // 从指定的资源文件中加载主工具栏菜单
                    inflateMenu(R.menu.menu_toolbar_main)
                    // 为菜单项设置点击监听器，当菜单项被点击时执行特定操作
                    setOnMenuItemClickListener {
                        configureSearchAppBar(baseActivity)
                        true
                    }
                    logo = null
                }
            }
        }

        /**
         * 配置搜索应用栏的静态方法。
         * 该方法更新应用栏和搜索输入框的属性，以显示搜索状态。
         *
         * @param baseActivity 基础活动，其应用栏需要配置为搜索状态。
         */
        private fun configureSearchAppBar(baseActivity: BaseActivity) {
            baseActivity.apply {
                searchLayout?.updateLayoutParams {
                    width = ViewGroup.LayoutParams.WRAP_CONTENT
                }
                searchTextInputLayout?.apply {
                    isVisible = true
                }
                mainAppToolbar?.apply {
                    title = null
                    setNavigationOnClickListener {
                        configureDefaultAppBar(baseActivity)
                    }
                    menu?.clear()
                    logo = null
                }
                searchTextInputEditText?.apply {
                    post {
                        requestFocus()
                        showKeyboard()
                    }
                }
            }
        }
    }

    /**
     * 表示专辑列表屏幕的可组合函数。
     * 该函数根据UI状态显示不同的UI元素，如加载指示器、数据不可找到动画或相册网格。
     *
     * @param viewModel 专辑列表视图模型，提供UI所需的数据。
     */
    @Composable
    private fun AlbumListScreen(viewModel: AlbumListViewModel) {
        val uiState: UiState by viewModel.uiStateFlow.collectAsStateWithLifecycle()

        uiState.let {
            when (it) {
                Error -> DataNotFoundAnim()
                Loading -> ProgressIndicator()
                is Content -> PhotoGrid(albums = it.albums, viewModel)
            }
        }
    }

    /**
     * 表示相册网格的可组合函数。
     * 该函数使用LazyVerticalGrid来显示相册列表，并为每个相册显示一个卡片。
     *
     * @param albums 相册列表。
     * @param viewModel 专辑列表视图模型，处理相册点击事件。
     */
    @Composable
    private fun PhotoGrid(albums: List<Album>, viewModel: AlbumListViewModel) {
        LazyVerticalGrid(
            columns = GridCells.Adaptive(Dimen.imageSize),
            contentPadding = PaddingValues(Dimen.screenContentPadding)
        ) {
            items(items = albums, key = { it.id }) { album ->
                ElevatedCard(
                    modifier = Modifier
                        .padding(Dimen.spaceS)
                        .wrapContentSize(),
                    onClick = { viewModel.onAlbumClick(album) },
                ) {
                    PlaceholderImage(
                        url = album.getDefaultImageUrl(),
                        contentDescription = stringResource(id = R.string.album_cover_content_description),
                        modifier = Modifier.size(Dimen.imageSize),
                    )
                }
            }
        }
    }
}
